package com.flx.cloud.sentinel.service.impl;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.flx.cloud.sentinel.service.SentinelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Fenglixiong
 * @Create 2022/4/22 18:49
 * @Description
 **/
@Slf4j
@Service
public class SentinelServiceImpl implements SentinelService {

    /**
     * 表示被限制资源
     * @param name
     * @return
     */
    public String testHello(String name){
        return "Hello,"+name;
    }

    @SentinelResource(value = "testBlockHandler",blockHandler = "defaultBlockHandler")
    public String testBlockHandler(String name){
        return "block,"+name;
    }

    @SentinelResource(value = "testFallbackHandler",fallback = "defaultFallbackHandler")
    public String testFallbackHandler(String name){
        if(name.equals("error")){
            throw new RuntimeException("error");
        }
        if(name.equals("timeout")){
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "fallback,"+name;
    }



    public String testGetInfo(){
        Entry entry = null;
        try{
            entry = SphU.entry("getInfo");
            return "success";
        }catch (BlockException e) {
            e.printStackTrace();
            return "访问过于频繁，已经被限流了！";
        }finally {
            if(entry!=null){
                entry.exit();
            }
        }
    }

    /**
     * 默认流控异常处理器
     * @param
     * @return
     */
    public String defaultBlockHandler(String name,BlockException e){
        log.info("触发默认限流策略，请稍后再试,error = {}",e.toString());
        return "触发默认限流策略，请稍后再试一下哦！";
    }

    /**
     * 默认流控异常处理器
     * @param
     * @return
     */
    public String defaultFallbackHandler(String name,Throwable e){
        log.info("触发默认异常降级，请稍后再试,error = {}",e.toString());
        return "触发默认异常降级，请稍后再试一下哦！";
    }

    /**
     * 加载配置规则
     * resource: 规则的资源名
     * grade: 限流阈值类型，qps 或线程数
     * count: 限流的阈值
     * limitApp: 被限制的应用，授权时候为逗号分隔的应用集合，限流时为单个应用
     * strategy: 基于调用关系的流量控制
     * controlBehavior：流控策略
     */
    @PostConstruct
    public void initRule(){
        List<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule();
        rule.setRefResource("getInfo");
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(3);
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}
